package org.db2.project.airline.dao.impl;

import org.db2.project.airline.dao.DAOException;
import org.db2.project.airline.dao.FlightPlanDAO;
import org.db2.project.airline.model.Airport;
import org.db2.project.airline.model.FlightClassType;
import org.db2.project.airline.model.FlightPlan;
import org.hibernate.HibernateException;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

/**
 *
 */
public class HibernateFlightPlanDAO extends HibernateGenericDAO<FlightPlan> implements FlightPlanDAO {

    public HibernateFlightPlanDAO() {
        // empty constructor
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<FlightPlan> find(Airport departureAirport, Airport arrivalAirport,
                                 FlightClassType flightClassType, Date departureTime, Date arrivalTime,
                                 boolean twoDaysSpan) throws DAOException {
        try {
            Date twoDayDepartureDate = getTwoDaysDate(departureTime);
            Date twoDayArrivalTime = getTwoDaysDate(arrivalTime);

            return getSession()
                    .createQuery("select plan " +
                            " from FlightPlan plan " +
                            " join plan.flightRoute flightRoute " +
                            " join flightRoute.departureAirport depAirport " +
                            " join flightRoute.destinationAirport destinationAirport " +
                            " join plan.flight flight " +
                            " join flight.airplane airplane, " +
                            " FlightClass flightClass " +
                            " join flightClass.flightClassType flightClassType " +
                            " where depAirport.id = :departureAirportId " +
                            " and destinationAirport.id = :destinationAirportId " +
                            " and flightClass.airplane.id = airplane.id " +
                            " and flightClassType.id = :flightClassTypeId " +
                            " and ((:twoDaysSpan = false" +
                            " and plan.departureTime >= :departureTime " +
                            " and plan.arrivalTime <= :arrivalTime) " +
                            " or (:twoDaysSpan = true " +
                            " and plan.departureTime >= :twoDayDepartureTime " +
                            " and plan.arrivalTime <= :twoDayArrivalTime)) " +
                            " order by plan.departureTime desc")
                    .setParameter("departureAirportId", departureAirport.getId())
                    .setParameter("destinationAirportId", arrivalAirport.getId())
                    .setParameter("flightClassTypeId", flightClassType.getId())
                    .setParameter("departureTime", departureTime)
                    .setParameter("arrivalTime", arrivalTime)
                    .setParameter("twoDayDepartureTime", twoDayDepartureDate)
                    .setParameter("twoDayArrivalTime", twoDayArrivalTime)
                    .setParameter("twoDaysSpan", twoDaysSpan)
                    .list();
        } catch (HibernateException e) {
            throw new DAOException("Error occurred when retrieving entities from persistence.", e);
        }
    }

    private Date getDate(Date date) {

        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        return calendar.getTime();
    }

    private Date getTwoDaysDate(Date date) {
        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_MONTH, 2);
        return calendar.getTime();
    }
}
